#include "ThreadPool.h"
#include "Thread.h"
#include <unistd.h>
#include <iostream>

using std::cout;
using std::endl;

ThreadPool::ThreadPool(size_t threadNum, size_t queSize)
: _threadNum(threadNum)
, _queSize(queSize)
, _taskQue(_queSize)
, _isExit(false)
{
    //为了防止频繁扩容，就预留空间
    _threads.reserve(_threadNum);
}

ThreadPool::~ThreadPool()
{

}

//线程池的启动与停止
void ThreadPool::start()
{
    //1、创建工作线程
    for(size_t idx = 0; idx != _threadNum; ++idx)
    {
        unique_ptr<Thread> up(new Thread(std::bind(&ThreadPool::doTask, this)));
        _threads.push_back(std::move(up));
    }
    //2、启动所有的工作线程
    for(auto &th : _threads)
    {
        th->start();//将所有的工作线程都运行起来了
    }
}

void ThreadPool::stop()
{
    //现在没有机制能保证子线程将所有的任务执行完毕之后才退出？
    //解决方案：只要任务队列中有任务，就不能回收子线程
    while(!_taskQue.empty())
    {
        sleep(1);
    }

    _isExit = true;//线程池马上要退出，可以将标志位设置为true
    //将所有的在_notEmpty条件变量上的线程全部唤醒，然后让主线程回收
    _taskQue.wakeup();

    for(auto &th : _threads)
    {
        th->stop();//将所有的工作线程都停止运行
    }
}

//添加任务
void ThreadPool::addTask(Task &&task)
{
    if(task)
    {
        _taskQue.push(std::move(task));
    }
}

//获取任务
Task ThreadPool::getTask()
{
    return _taskQue.pop();
}

//线程池交给工作线程执行的任务
void ThreadPool::doTask()
{
    while(!_isExit)
    {
        Task taskcb = getTask();//pop
        if(taskcb)
        {
            taskcb();//需要执行的任务，回调函数的执行
        }
        else
        {
            cout << "ptask == nullptr" << endl;
        }
    }
}
